import java.net.Socket;
import java.net.ServerSocket;
import java.text.ParseException;
import java.io.*;
import java.util.*;

public class WebServer extends Thread{

    /*@static variables*/

    private static final int backlog = 10;
    private static Config webconf;

    /*@instance variables*/

    private Socket clientSocket;
    private ServerSocket serverSocket;
    private PrintWriter out;
    private BufferedReader in;
    private Connections webconn;

    public WebServer() throws Exception {
        webconn = new Connections();
        webconf = SIPSpeaker.conf;
    }

    @Override
    public void run() {
        
        try
        {
            System.out.println("Starting new WebServer on "+webconf.http_interface.getHostAddress()+":"+webconf.http_port);
            serverSocket = new ServerSocket(webconf.http_port, backlog,webconf.http_interface);
        }
        catch (IOException ex)
        {
            ex.printStackTrace();
        }

        while (true)
        {
            try
            {
                //Accept a client connection
                clientSocket = webconn.ConnectToClientSocket(serverSocket);
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                out = new PrintWriter(clientSocket.getOutputStream(),true);
                
                //Capture the HTTP header and request
                String[] httpRequest = GetHttpRequest();
                //Check what kind of request we have
                switch (HttpHeaderType(httpRequest))
                {
                    case 1:
                    {
                        ShowInputPage();
                        break;
                    }
                    case 2:
                    {
                        WavManager.RecordMessage(httpRequest[httpRequest.length-1]);
                        break;
                    }
                    case 3:
                    {
                        ShowCurrentMessage();
                        break;
                    }
                }
                out.close();
                in.close();
                webconn.DisconnectFromClientSocket(clientSocket);
            }
            catch (Exception e)
            {
                ReturnPage(e.toString());
            }
            finally
            {
                try 
                {
                    out.close();
                    in.close();
                    webconn.DisconnectFromClientSocket(clientSocket);
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }
        }
    }

    private String[] GetHttpRequest() throws IOException {

        List <String> request = new ArrayList<String>();

        String inputLine = in.readLine();
        request.add(inputLine);

        boolean postFlag = false;
        if (inputLine.matches("^POST / HTTP/1\\..$")) { postFlag = true; }

        int contentLength = 0;

        while (!(inputLine=in.readLine()).equals(""))
        {
            if (inputLine.matches("^Content-Length: [0-9]+"))
            {
                String lengthString = inputLine.replaceAll("Content-Length: ","").trim();
                contentLength = Integer.parseInt(lengthString);
            }
            request.add(inputLine);
        }

        if (postFlag == true)
        {
            char [] buf = new char[contentLength];
            in.read(buf);
            request.add(new String(buf));
        }

        String [] httpRequest = request.toArray(new String[request.size()]);
        return httpRequest;

    }

    private int HttpHeaderType(String[] args) throws ParseException {

        //Let's see if we have a GET request
        if (args[0].matches("^GET /(\\?)? HTTP/1\\..$"))
        {
            return 1;
        }

        //Or a POST request to record the message
        if (args[0].matches("^POST / HTTP/1\\..$"))
        {
            return 2;
        }

        //Or show the current message
        if (args[0].matches("^GET /show\\? HTTP/1\\..$"))
        {
            System.out.println("Showing current message");
            return 3;
        }

        //Or something like GET /favicon.ico?
        if (args[0].matches("^GET /.* HTTP/1\\..$"))
        {
            return 4;
        }

        //Or something invalid
        throw new ParseException("Invalid type of request",0);
    }

    private void ShowInputPage() throws IOException {
        out.println("HTTP/1.1 200 OK");
        out.println("Content-Type: text/html\r\n");

        BufferedReader reader = null;
        try
        {
            reader = new BufferedReader(new FileReader(new File("").getAbsolutePath()+"/input_form.html"));
            String inputLine = null;
            while ((inputLine=reader.readLine()) != null)
            {
                out.println(inputLine);
            }
        }
        catch (IOException ex)
        {
            System.out.println(ex.getMessage());
            ReturnPage(ex.getMessage());
        }
        finally
        {
            reader.close();
        }
    }

    private void RecordMessage(String[] args)   {

    }

    private void ReturnPage(String args) {
        out.println("HTTP/1.1 200 OK");
        out.println("Content-Type: text/html\r\n");
        out.println("<html><body>");
        //TODO: add error webpage display logic here
        String exceptionType = args.split(":")[0];
        String errorMessage = args.replaceFirst(exceptionType+": ","");
        out.println(errorMessage+"\r\n");
        out.println("<form action='' method=GET>");
        out.println("<input type=submit value='Try again'>");
        out.println("</form></body></html>");
    }

    private void ShowCurrentMessage() {
        throw new UnsupportedOperationException("Not yet implemented");
    }

}